//
//  BitStreamExtensions.swift
//  XWHASmartKit
//
//  Created by Riven on 2023/10/10.
//

import Foundation

func isLittleEndian() -> Bool {
    var value : UInt16 = 0x0025
    let data = Data(bytes:&value, count:2)
    let bytes = [UInt8](data)
    
    print(bytes)
    // 输出：0x25 0x00 小端
    
    if bytes[0] == 0x25 {
        return true
    }
    
    return false
}

public func toByteArray<T>(value: T) -> [UInt8] {
    var value = value
    let bytes = withUnsafeBytes(of: &value,{$0.map({$0})})
    return bytes
}

public func byteArrayToType<T>(_ value:[UInt8]) -> T {
    return value.withUnsafeBytes({$0.load(as:T.self)})
}

public func add<T:FixedWidthInteger>(toBuf:inout [UInt8],_ value:T){
    let size = MemoryLayout<T>.size
    for i in 1...size {
        let distance = (size - i) * 8;
        let sub  = (value >> distance) & 0xff
        let value = UInt8(sub & 0xff)
        toBuf.append(value)
    }
}

// MARK: - 整数类型转换扩展（基于 BinaryInteger 协议）
public extension BinaryInteger {
    
    func castingToFloatingPoint<T: BinaryFloatingPoint>() -> T {
        return T(self)
    }
    
    // MARK: 溢出截断转换（超出范围时截断高位，保留低位）
    func truncatedCastingTo<T: BinaryInteger>() -> T {
        return T(truncatingIfNeeded: self)
    }
    
    /// 截断转换为 Int8（溢出时截断高位）
    func truncatedToInt8() -> Int8 { Int8(truncatingIfNeeded: self) }
    /// 截断转换为 Int16（溢出时截断高位）
    func truncatedToInt16() -> Int16 { Int16(truncatingIfNeeded: self) }
    /// 截断转换为 Int32（溢出时截断高位）
    func truncatedToInt32() -> Int32 { Int32(truncatingIfNeeded: self) }
    /// 截断转换为 Int64（溢出时截断高位）
    func truncatedToInt64() -> Int64 { Int64(truncatingIfNeeded: self) }
    
    func truncatedToInt() -> Int { Int(truncatingIfNeeded: self) }
    
    /// 截断转换为 UInt8（溢出时截断高位）
    func truncatedToUInt8() -> UInt8 { UInt8(truncatingIfNeeded: self) }
    /// 截断转换为 UInt16（溢出时截断高位）
    func truncatedToUInt16() -> UInt16 { UInt16(truncatingIfNeeded: self) }
    /// 截断转换为 UInt32（溢出时截断高位）
    func truncatedToUInt32() -> UInt32 { UInt32(truncatingIfNeeded: self) }
    /// 截断转换为 UInt64（溢出时截断高位）
    func truncatedToUInt64() -> UInt64 { UInt64(truncatingIfNeeded: self) }
    
    func truncatedToUInt() -> UInt { UInt(truncatingIfNeeded: self) }
    
    // MARK: 安全转换（超出范围时返回 nil）
    func safeCastingTo<T: BinaryInteger>() -> T? {
        return T(exactly: self)
    }
    
    /// 安全转换为 Int8（超出范围返回 nil）
    func safeToInt8() -> Int8? { Int8(exactly: self) }
    /// 安全转换为 Int16（超出范围返回 nil）
    func safeToInt16() -> Int16? { Int16(exactly: self) }
    /// 安全转换为 Int32（超出范围返回 nil）
    func safeToInt32() -> Int32? { Int32(exactly: self) }
    /// 安全转换为 Int64（超出范围返回 nil）
    func safeToInt64() -> Int64? { Int64(exactly: self) }
    /// 安全转换为 Int（超出范围返回 nil）
    func safeToInt() -> Int? { Int(exactly: self) }
    
    /// 安全转换为 UInt8（超出范围返回 nil）
    func safeToUInt8() -> UInt8? { UInt8(exactly: self) }
    /// 安全转换为 UInt16（超出范围返回 nil）
    func safeToUInt16() -> UInt16? { UInt16(exactly: self) }
    /// 安全转换为 UInt32（超出范围返回 nil）
    func safeToUInt32() -> UInt32? { UInt32(exactly: self) }
    /// 安全转换为 UInt64（超出范围返回 nil）
    func safeToUInt64() -> UInt64? { UInt64(exactly: self) }
    /// 安全转换为 UInt（超出范围返回 nil）
    func safeToUInt() -> UInt? { UInt(exactly: self) }
    
    // MARK: 强制转换（超出范围时会崩溃，谨慎使用）
//    /// 转换为 Int8（强制转换，超出范围崩溃）
//    func toInt8() -> Int8 { Int8(self) }
//    /// 转换为 Int16（强制转换，超出范围崩溃）
//    func toInt16() -> Int16 { Int16(self) }
//    /// 转换为 Int32（强制转换，超出范围崩溃）
//    func toInt32() -> Int32 { Int32(self) }
//    /// 转换为 Int64（强制转换，超出范围崩溃）
//    func toInt64() -> Int64 { Int64(self) }
//    /// 转换为 Int（强制转换，超出范围崩溃）
//    func toInt() -> Int { Int(self) }
//
//    /// 转换为 UInt8（强制转换，超出范围崩溃）
//    func toUInt8() -> UInt8 { UInt8(self) }
//    /// 转换为 UInt16（强制转换，超出范围崩溃）
//    func toUInt16() -> UInt16 { UInt16(self) }
//    /// 转换为 UInt32（强制转换，超出范围崩溃）
//    func toUInt32() -> UInt32 { UInt32(self) }
//    /// 转换为 UInt64（强制转换，超出范围崩溃）
//    func toUInt64() -> UInt64 { UInt64(self) }
//    /// 转换为 UInt（强制转换，超出范围崩溃）
//    func toUInt() -> UInt { UInt(self) }
    
}

public extension BinaryFloatingPoint {
    
    func castingToBinaryInteger<T: BinaryInteger>() -> T {
        return T(self)
    }
    
}

// MARK: - 使用示例
//func testIntegerConversions() {
//    // 1. 基础转换（在范围内）
//    let int8: Int8 = 100
//    let int16 = int8.toInt16() // 100（安全转换）
//    let uint8 = int8.safeToUInt8() // 100（可选值，成功）
//    
//    // 2. 安全转换（超出范围）
//    let largeInt: Int = 300
//    let safeUInt8 = largeInt.safeToUInt8() // nil（300 超出 UInt8 范围 0~255）
//    if let safe = safeUInt8 {
//        print("安全转换成功：\(safe)")
//    } else {
//        print("安全转换失败：值超出目标类型范围") // 输出此句
//    }
//    
//    // 3. 强制转换（超出范围会崩溃，仅用于确定值在范围内的场景）
//    let smallInt: Int = 200
//    let forceUInt8 = smallInt.toUInt8() // 200（成功，在范围内）
//    // let crashUInt8 = largeInt.toUInt8() // 运行时崩溃（300 > 255）
//    
//    // 4. 截断转换（溢出时保留低位）
//    let overflowInt: Int32 = 300 // 二进制：100101100
//    let truncatedUInt8 = overflowInt.truncatedToUInt8() // 44（二进制 101100，截断后 8 位）
//    print("截断转换结果：\(truncatedUInt8)") // 44
//    
//    // 5. 有符号与无符号转换
//    let negativeInt: Int8 = -50
//    let unsignedFromNegative = negativeInt.safeToUInt8() // nil（负数无法转换为无符号）
//    let truncatedUnsigned = negativeInt.truncatedToUInt8() // 206（-50 的补码截断后为 206）
//}

public extension Bool {
    
    var uint8: UInt8 {
        switch self {
        case true:
            return 0x01
        default:
            return 0x00
        }
    }
    
    func toUInt8() -> UInt8 {
        switch self {
        case true:
            return 0x01
        default:
            return 0x00
        }
    }
    
}

public extension UInt8 {
    
    var bool: Bool {
        switch self {
        case 0x01:
            return true
            
        default:
            return false
        }
    }
    
    var hexStr: String {
        let str = String(format:"0x%02x",self)
        return str
    }
    
    func toHexStr() -> String {
        return hexStr
    }
    
}

public extension FixedWidthInteger {
    
    // 大端模式（高位在前）
    var bytes: [UInt8] {
        let size = self.bitWidth / 8 // MemoryLayout<Self>.size
        if size == 1 {
            return [UInt8(self)]
        }
        var bytes = [UInt8]()
        for i in 0..<size {
            let distance = (size - 1 - i) * 8;
            let sub  = self >> distance
            let value = UInt8(sub & 0xff)
            bytes.append(value)
        }
        return bytes
    }
    
    var hexStr: String {
        bytes.hexStr
    }
    
    func toHexStr() -> String {
        return hexStr
    }
    
    var memoryLayoutBytes: [UInt8] {
        return bytes.reversed()
    }
    
    var memoryLayoutHexStr: String {
        memoryLayoutBytes.hexStr
    }
    
    func toMemoryLayoutHexStr() -> String {
        return memoryLayoutHexStr
    }
    
}

public extension Data {
    
    var byteArray: [UInt8] {
        return [UInt8](self)
    }
    
    var bytes: [UInt8] {
        return byteArray
    }
    
    var hexStr: String {
        var str = ""
        for byte in self.byteArray {
            str += byte.hexStr
            str += " "
        }
        return str
    }
    
    init(hexStr: String) {
        self.init(Array<UInt8>(hexStr: hexStr))
    }
    
    //    var bytes: Array<UInt8> {
    //        return Array(self)
    //    }
    //MARK: Data转十六进制字符串
    /// Create hexadecimal string representation of `Data` object.
    ///
    /// - returns: `String` representation of this `Data` object.
    func toHexStr() -> String {
        return byteArray.toHexStr()
    }
    
}

public extension Array {
    init(reserveCapacity: Int) {
        self = Array<Element>()
        self.reserveCapacity(reserveCapacity)
    }
    
    var slice: ArraySlice<Element> {
        return self[self.startIndex ..< self.endIndex]
    }
}

public extension Array where Element == UInt8 {
    
    var hexStr: String {
        return `lazy`.reduce("") {
            var s = String($1, radix: 16)
            if s.count == 1 {
                s = "0" + s
            }
            return $0 + s
        }
    }
    
    init(hexStr: String) {
        self.init(reserveCapacity: hexStr.unicodeScalars.lazy.underestimatedCount)
        var buffer: UInt8?
        var skip = hexStr.hasPrefix("0x") ? 2 : 0
        for char in hexStr.unicodeScalars.lazy {
            guard skip == 0 else {
                skip -= 1
                continue
            }
            guard char.value >= 48 && char.value <= 102 else {
                removeAll()
                return
            }
            let v: UInt8
            let c: UInt8 = UInt8(char.value)
            switch c {
            case let c where c <= 57:
                v = c - 48
            case let c where c >= 65 && c <= 70:
                v = c - 55
            case let c where c >= 97:
                v = c - 87
            default:
                removeAll()
                return
            }
            if let b = buffer {
                append(b << 4 | v)
                buffer = nil
            } else {
                buffer = v
            }
        }
        if let b = buffer {
            append(b)
        }
    }
    
    func toHexStr() -> String {
        return hexStr
    }
    
}

public extension Int8 {
    
    func toDouble() -> Double {
        return Double(self)
    }
    
}

public extension UInt8 {
    
    func toBool() -> Bool {
        switch self {
        case 0x00:
            return false
            
        default:
            return true
        }
    }
    
    func toUInt8ToInt() -> Int {
        return Int(self)
    }
    
    func toInt8ToInt() -> Int {
        return Int(Int8(bitPattern: self))
    }
    
}

public extension Int {
    
    func toInt8() -> Int8 {
        return Int8(truncatingIfNeeded: self)
    }
    
    func toUInt8() -> UInt8 {
        //        return UInt8(bitPattern: Int8(self))
        return  UInt8(truncating: self as NSNumber)
        //        return unsafeBitCast(self, to: UInt8.self)
    }
    
    func toInt32() -> Int32 {
        return Int32(truncatingIfNeeded: self)
    }
    
}

public extension Double {
    
    func toInt() -> Int {
        if self.isNaN {
            return Int.zero
        }
        if self.isInfinite {
            return Int.max
        }
        
        if self > Double(Int.max) {
            return Int.max
        }
        if self < Double(Int.min) {
            return Int.min
        }
        
        let toInt = Int(self)
        return toInt
    }
    
    func toInt8() -> Int8 {
        return toInt().toInt8()
    }
    
    func toUInt8() -> UInt8 {
        return toInt().toUInt8()
    }
    
}
